// Copyright (C) 2008 Taylor L. Riche <riche@cs.utexas.edu>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

/**
 * 
 */
package appcomp.entities;

import core.CodeGenerator;
import core.Entity;
import java.util.HashMap;

/**
 * @author riche
 *
 */
public class Port extends Entity {

	/**
	 * @author riche
	 * An enumerated type representing the direction of data through the particular Port instance.
	 */
	public enum Direction {
		IN, OUT
	}
	
	protected String handler;
	protected String predicate;
	protected Direction direction;
	protected Type type;
	protected Connector conn = null;
	protected int index;
	
	public Port() {
		
	}
	
	/**
	 * @param name
	 * @param handler
	 * @param direction
	 */
	public Port(final String name, final String handler, final String predicate, final Direction direction, final Type type) {
		this.setName(name);
		this.handler = handler;
		this.direction = direction;
		this.type = type;
		this.predicate = predicate;
	}
	public static Port create(String name, String handler, String predicate, Direction direction, Type type) {
		return new Port(name, handler, predicate, direction, type);
	}
	/**
	 * @return the direction
	 */
	public Direction getDirection() {
		return direction;
	}
	/**
	 * @return the handler
	 */
	public String getHandler() {
		return handler;
	}
	/**
	 * @return the type
	 */
	public Type getType() {
		return type;
	}
	
	/* (non-Javadoc)
	 * @see appcomp.entities.Entity#generateCode()
	 */
	@Override
	public void generateCode(CodeGenerator cg) {
		if(this.getDirection() == Port.Direction.IN) {
			this.getFile().println("\tvoid " + this.handler + "(" + this.type.getCoreType() + " * data, unsigned long dataSize);");
			this.getFile().println("\t" + this.type.getCoreType() + " * gen" + this.getName() + "Request();");
		}
		else {
			this.getFile().println("\tvoid " + this.getName() + "(" + this.type.getCoreType() + " * data, unsigned long dataSize) {");
			this.getFile().println("\t\tif(!inProf) {");
			this.getFile().println("\t\tlagniappe::CoreOp * op = destVec.at(" + this.index + ")->first;");
			this.getFile().println("\t\tuint32_t port = destVec.at(" + this.index + ")->second;");
			this.getFile().println("\t\tlagniappe::RCon * rc = new lagniappe::RCon(op, static_cast<lagniappe::RData *>(data), port, dataSize);");
			//this.getFile().println("\t\top->getProc(data)->processRequest(rc);");
			//this.getFile().println("\t\tdelete data;");
			this.getFile().println("\t\top->run(rc);}");
			this.getFile().println("\t}");
		}
		
	}
	public void generateCodeCases() {
		this.getFile().println(this.index + ") {" + this.getHandler() + "(static_cast<" + this.type.getCoreType() + " *>(rcon->getRData()), rcon->getSize());}");
		this.getFile().println();
	}
	public void generateInclude(HashMap<String, Boolean> includeMap) {
		if(type != null && this.type.getFileURI() != null) {
			if(!includeMap.containsKey(this.type.getFileURI().toString())) { 
			    this.getFile().println("#include \"" + this.type.getFileURI().toString() + "\"");
			    includeMap.put(this.type.getFileURI().toString(), true);
			}
		}
	}
	/**
	 * @return the conn
	 */
	public Connector getConn() {
		return conn;
	}
	/**
	 * @param conn the conn to set
	 */
	public void setConn(Connector conn) {
		this.conn = conn;
	}
	
	/**
     * @return the predicate
     */
    public String getPredicate() {
        return predicate;
    }

    /**
     * @param predicate the predicate to set
     */
    public void setPredicate(String predicate) {
        this.predicate = predicate;
    }

    public String printFullName() {
		return this.getName() + ":" + this.getDirection();
	}

    public void setIndex(int i) {
        this.index = i;
    }
    
    public int getIndex() {
        return this.index;
    }
    
}
